﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;

namespace Wombat.DbToDwAdapter
{
    public class FactInterpolationService : IFactAggregationService
    {
        public IEnumerable<InterpolatedFloatData> GetAggregatedFloatData(RawFloatData futureValue, DateTime lastAggregationTime,
                                                                         DateTime tagNewAggregation, int aggregationMinutes)
        {
            var intPoint = lastAggregationTime.AddMinutes(aggregationMinutes);
            while (intPoint <= tagNewAggregation)
            {
                var intPointId = GetFactTimeId(intPoint, aggregationMinutes);
                if (IsNotNumber(futureValue.Value) || IsNotNumber(futureValue.LeftDeviation))
                    yield return
                        new InterpolatedFloatData
                            {
                                InterpolatedTime = intPointId,
                                IsNan = true,
                                TagId = futureValue.TagId,
                                Value = null
                            };

                var dTime = (futureValue.Time - intPoint).Ticks;
                var interpolatedValue = futureValue.Value - dTime*futureValue.LeftDeviation;
                yield return new InterpolatedFloatData()
                                 {
                                     InterpolatedTime = intPointId,
                                     TagId = futureValue.TagId,
                                     Value = interpolatedValue
                                 };
                intPoint = intPoint.AddMinutes(aggregationMinutes);
            }
        }

        private static bool IsNotNumber(double? value)
        {
            return value == null || double.IsNaN(value.Value) ||
                   double.IsInfinity(value.Value);
        }

        private static long GetFactTimeId(DateTime time, int interpolationMinutes)
        {
            Contract.Assert((time.Minute % interpolationMinutes) == 0);
            return time.Year*100000000 + time.Month*1000000 + time.Day*10000 + time.Hour*100 + interpolationMinutes;
        }

    }
}